home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / readall.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  3KB  |  136 lines

  1. /* readall - read a whole device fast        Author: Andy Tanenbaum */
  2.  
  3. /* Readall reads all the blocks on a device as fast as it can.  If it hits
  4.  * an error, it stops reading in large units and reads one block at a time.
  5.  * It reports on all errors it finds.
  6.  *
  7.  * If the -b flag is given, the output is a shell script that can be run
  8.  * to mark all the bad blocks.
  9.  *
  10.  * If the -t flag is given, only the total numbers of blocks is reported.
  11.  *
  12.  * Examples of usage:
  13.  *    readall /dev/hd1        # read /dev/hd1
  14.  *    readall -b /dev/hd2        # prepare bad block list on stdout
  15.  *    readall -t /dev/ram        # report size of ram disk
  16.  */
  17.  
  18. #include <sys/types.h>
  19. #include <fcntl.h>
  20. #include <unistd.h>
  21. #include <blocksize.h>
  22.  
  23. #define CHUNK    25        /* max number of blocks read at once */
  24. #define RESUME  200        /* # good reads before going back to CHUNK */
  25. #define DIVISOR     50        /* how often to print statistics */
  26. #define STORE  4096        /* save this many bad blocks for summary */
  27.  
  28. int chunk = CHUNK;        /* current number of blocks being read */
  29. long goodies;            /* incremented on good reads */
  30. long errors;            /* number of errors so far */
  31. int normal = 1;            /* set unless -b flag is given */
  32. int total = 0;            /* unset unless -t flag is given */
  33. char *name;            /* name of special file being read */
  34.  
  35. char a[CHUNK * BLOCK_SIZE];    /* read buffer */
  36. long rotten[STORE];        /* list of bad blocks */
  37.  
  38. main(argc, argv)
  39. int argc;
  40. char *argv[];
  41. {
  42.   int fd, s, i, badprinted;
  43.   long b = 0;
  44.   char *p;
  45.  
  46.   if (argc != 2 && argc != 3) {
  47.     printf("Usage: readall [-b | -t] file\n");
  48.     exit(1);
  49.   }
  50.  
  51.   i = 1;
  52.  
  53.   p = argv[1];
  54.   if (*p == '-' && *(p+1) == 'b' && *(p+2) == '\0') {
  55.     normal = 0;
  56.     i++;
  57.     name = argv[i];
  58.   }
  59.   if (*p == '-' && *(p+1) == 't' && *(p+2) == '\0') {
  60.     normal = 0;
  61.     total = 1;
  62.     i++;
  63.     name = argv[i];
  64.   }
  65.  
  66.   fd = open(argv[i], O_RDONLY);
  67.   if (fd < 0) {
  68.     printf("%s is not readable\n", argv[i]);
  69.     exit(1);
  70.   }
  71.  
  72.   /* Read the entire file. Try it in large chunks, but if an error occurs,
  73.    * go to single reads for a while.
  74.    */
  75.   while (1) {
  76.     lseek(fd, BLOCK_SIZE * b, SEEK_SET);
  77.     s = read(fd, a, BLOCK_SIZE * chunk);
  78.     if (s == BLOCK_SIZE * chunk) {
  79.         /* Normal read, no errors. */
  80.         b += chunk;
  81.         goodies++;
  82.         if (chunk == 1) {
  83.             if(goodies >= RESUME && b % DIVISOR == 0)chunk = CHUNK;
  84.         }
  85.     } else if (s < 0) {
  86.         /* I/O error. */
  87.         if (chunk != 1) {
  88.             chunk = 1;    /* regress to single block mode */
  89.             continue;
  90.         }
  91.         if (errors == STORE) {
  92.              printf("\n%ld Bad blocks is too many.  Exiting\n",errors);
  93.              exit(1);
  94.         }
  95.         rotten[(int)errors] = b;    /* log the error */
  96.         b += chunk;
  97.         errors++;
  98.     } else {
  99.         /* End of file. */
  100.         b += s/BLOCK_SIZE;
  101.         if (normal) {
  102.             output(b);
  103.             printf("\n");
  104.         }
  105.         if (total) printf("%8ld\n", b);
  106.         if ((errors == 0) || total) exit(0);
  107.         if (normal) 
  108.             printf("Summary of bad blocks\n");
  109.         else
  110.             badprinted = 0;
  111.  
  112.         /* Print summary of bad blocks, possibly as shell script. */
  113.         for (i = 0; i < errors; i++) {
  114.             if (normal == 0 && badprinted == 0) {
  115.                 printf("badblocks %s ", name);
  116.                 badprinted = 1;
  117.             }
  118.             printf("%6ld ", rotten[i]);
  119.             if ( (i+1) % 7 == 0) {
  120.                 printf("\n");
  121.                 badprinted = 0;
  122.             }
  123.         }
  124.         printf("\n");
  125.         exit(0);
  126.     }
  127.     if (normal && b % DIVISOR == 0) output(b);
  128.   }
  129. }
  130.  
  131. output(b)
  132. long b;
  133. {
  134.   printf("%8ld blocks read, %5ld errors\r", b, errors);
  135. }
  136.